/*
 * @Author: gonglf
 * @Date: 2022-09-26 11:31:44
 * @LastEditors: gonglf
 * @LastEditTime: 2022-09-26 14:58:14
 * @Description:
 *
 */
package main

import (
	"context"
	"fmt"
	"os"
	"os/signal"
	"syscall"

	"gitee.com/gonglf1212/chanrpc"
	"github.com/gocpp/log"
	"go.uber.org/zap"
)

type Server struct {
	Rpc      *chanrpc.ChanRPC
	Ctx      context.Context    // 上下文控制
	CbCancel context.CancelFunc // 结束子协程
}

func main() {
	s := &Server{
		Rpc: chanrpc.NewChanRPC(64),
	}

	s.Rpc.Register("login", s.login)
	s.Rpc.Register("start_game", s.startGame)
	s.Rpc.Register("get_age", s.getAge)

	s.Ctx, s.CbCancel = context.WithCancel(context.Background())

	go s.GoCallback(s.Ctx)

	s.Rpc.Send("login", &User{
		Name: "你好",
		Age:  11,
	})
	s.Rpc.Send("start_game")                 //不带参数
	age, err := s.Rpc.Call("get_age", &User{ //带有参数返回
		Age: 100,
	})
	if err == nil {
		fmt.Println("年龄", age[0].(int))
	}

	handlerSignal(s)
}

func (s *Server) GoCallback(ctx context.Context) {
	for {
		select {
		case <-ctx.Done():
			return
		case request := <-s.Rpc.R():
			if err := s.Rpc.Exec(request); err != nil {
				log.Error("GoCallback rpc.Exec fail", zap.Error(err))
			}
		}
	}
}

func (s *Server) Destroy() {
	s.CbCancel()
}

type User struct {
	Name string
	Age  int
}

func (s *Server) login(user *User) {
	fmt.Println("--login--", user.Name, user.Age)
}

func (s *Server) startGame() {
	fmt.Println("开始游戏")
}

func (s *Server) getAge(user *User) (age int, err error) {
	return user.Age, nil
}

func handlerSignal(srv *Server) {
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
	for {
		s := <-c
		log.Info("handlerSignal get a signal", zap.String("sig", s.String()))
		switch s {
		case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
			srv.Destroy()
			return
		case syscall.SIGHUP:
		default:
			return
		}
	}
}
